use gloo_console::log;
use web_sys::HtmlInputElement;
use yew::{platform::spawn_local, prelude::*};
use yew_router::prelude::*;

use crate::{
  api::user::{api_login, api_me, LoginResponse, MeResponse},
  components::alert::Alert,
  contexts::{
    CurrentUserActions, CurrentUserContext, CurrentUserDispatchActions,
  },
  Route,
};

use super::input::Input;

async fn login(
  username: String,
  password: String,
) -> Result<(LoginResponse, MeResponse), gloo_net::Error> {
  let result_token = api_login(username, password).await?;
  let result_user_info = api_me(&result_token.token).await?;

  Ok((result_token, result_user_info))
}

#[function_component]
pub fn LoginForm() -> Html {
  let username_handle = use_state(String::default);
  let password_handle = use_state(String::default);
  let username = (*username_handle).clone();
  let password = (*password_handle).clone();

  let navigator = use_navigator().expect("Navigator not available");
  let current_user_ctx = use_context::<CurrentUserContext>()
    .expect("Current user context is missing");

  let error_message_hander = use_state(String::default);
  let error_message = (*error_message_hander).clone();

  let username_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlInputElement>();
      if let Some(input) = target {
        username_handle.set(input.value());
      }
      // log!("username_changed");
    }
  };
  let password_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlInputElement>();
      if let Some(input) = target {
        password_handle.set(input.value());
      }
      // log!("password_changed");
    }
  };

  let c_username = username.clone();
  let c_password = password.clone();
  let onsubmit = {
    move |e: SubmitEvent| {
      e.prevent_default();
      // log!("onsubmit", c_username.clone(), c_password.clone());

      let c_username = c_username.clone();
      let c_password = c_password.clone();
      let c_error_message_hander = error_message_hander.clone();
      let c_navigator = navigator.clone();
      let c_current_user_ctx = current_user_ctx.clone();

      spawn_local(async move {
        match login(c_username, c_password).await {
          Ok(response) => {
            log!(format!("欢迎 {} 进入系统。", response.1.username));
            c_current_user_ctx.dispatch(CurrentUserDispatchActions {
              action_type: CurrentUserActions::LoginSuccess,
              login_response: Some(response.0),
              me_response: Some(response.1),
            });
            c_navigator.push(&Route::Home);
          }
          Err(err) => c_error_message_hander.set(err.to_string()),
        };
      });
    }
  };

  html! {
    <form {onsubmit}>
      if error_message.len() > 0 {
        <Alert message={error_message} alert_type="error"/>
      }
      <div>
        <Input
          name="username"
          label="Username"
          input_type="text"
          value={username}
          onchange={username_changed}
        />
      </div>

      <div>
        <Input
          name="password"
          label="Password"
          input_type="password"
          value={password}
          onchange={password_changed}
        />
      </div>

      <button type="submit">{"Login"}</button>
    </form>
  }
}
